import Glibc

class Timer {
    private let CLOCK_REALTIME = 0
    private var start_timespec = timespec()
    private var end_timespec = timespec()
    private var time_spec = timespec()
    func start() {
        clock_gettime(Int32(CLOCK_REALTIME),&start_timespec)
    }
    
    func stop() -> Double {
        clock_gettime(Int32(CLOCK_REALTIME),&end_timespec)
        let start_time = Double(start_timespec.tv_sec * 1_000_000 + start_timespec.tv_nsec / 1_000)
        let end_time = Double(end_timespec.tv_sec * 1_000_000 + end_timespec.tv_nsec / 1_000)
        let time = end_time - start_time
        return time / 1_000
    }
    func getTime() -> Double {
        clock_gettime(Int32(CLOCK_REALTIME),&time_spec)
        return Double(time_spec.tv_sec * 1_000_000 + time_spec.tv_nsec / 1_000)
    }
}

func GenerateFakeRandomInteger() -> [Int] {
    let resource: [Int] = [12, 43, 56, 76, 89, 54, 45, 32, 35, 47, 46, 44, 21, 37, 84]
    return resource;
}

func GenerateRandoms() -> [Int]{
    let result = Array(repeating: Int.random(in: 1..<3), count: 2)
    return result
}
var generaterandoms = GenerateRandoms()

func TimeGenerateRandoms() -> Double{
    let timer = Timer()
    timer.start()
    let tmp = 1
    if generaterandoms[tmp%2] != 0 {

    }
	let time = timer.stop()
    return time
}

var global = 0

/***************** With parameters *****************/
@inline(never)
func Foo(resources: [Int], i: Int, i3: Int, resourcesLength: Int) ->Int {
    var i4 = i3;
    if ((resources[i % Int(i3) & (resourcesLength - 1)] & 1) == 0) {
        i4 += 1;
    } else {
        i4 += 2;
    }
    return i4;
}

/***** Without parameters *****/
@inline(never)
func parameterlessFoo() {
    global += 1
}
/***************************** Default  parameters *****************************/
@inline(never)
func defaultFoo(_ a: Int! = 0, _ b: String! = "b", _ c: Bool! = true) {
    global += 1
}
/********************* Different  parameters *********************/
@inline(never)
func differentFoo(_ a: Int, _ b: String, _ c: Bool) {
    global += 1
}
/************************* Variable  parameters *************************/
@inline(never)
func variableFoo(_ a: Int?, _ b: String?, _ c: Bool?) {
    global += 1
}
/***************************** ...Args  parameters *****************************/
@inline(never)
func argsFoo(_ args: Int...) {
    global += 1
}
/***************** With parameters *****************/
// Normal call
func runNormalCall() -> Int {
    let count = 10000000
    let resources = GenerateFakeRandomInteger();
    var i3 = 1
    let timer = Timer()
    global = 0
    timer.start()
    let resourcesLength = resources.count
    for i in 0..<count {
        i3 = Foo(resources: resources, i: i, i3: i3, resourcesLength:resourcesLength)
    }
    let time = timer.stop()
    print("Function Call - RunNormalCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalCall()
/***** Without parameters *****/
// No parameter function call
func runParameterlessCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        parameterlessFoo()
    }
    let time = timer.stop()
    print("Function Call - RunParameterlessCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runParameterlessCall()
/************ Default  parameters *************/
// Normal call
func runNormalDefCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        defaultFoo()
    }
    let time = timer.stop()
    print("Function Call - RunNormalDefCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalDefCall()
/********************* Different  parameters *********************/
// Normal call
func runNormalDifCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        differentFoo(1, "1", true)
    }
    let time = timer.stop()
    print("Function Call - RunNormalDifferentCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalDifCall()
/************************* Variable  parameters *************************/
// Normal call
func runNormalVariableCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        variableFoo(1, "1", true)
    }
    let time = timer.stop()
    print("Function Call - RunNormalVariableFCall:\t"+String(time)+"\tms");
    return Int(time)
}
_ = runNormalVariableCall()
/***************************** ...Args  parameters *****************************/
// Normal call
func runNormalArgsCall() -> Int {
    let count = 10000000
    let timer = Timer()
    global = 0
    timer.start()
    for _ in 0..<count {
        argsFoo(1,2,3,4,5,6,7,8,9,10)
    }
    let time = timer.stop()
    print("...Args Parameter Normal Call:\t\(time)\tms")
    return Int(time)
}
print("Swift Method Call Is End, global value : \(global)")